<?php
/**
 * 上传类
 * @package core
 * @subpackage class
 * @author
 * @version $Id$
 */
class Upload extends Application {
	/* 成员变量 */
	protected $_type = array(
		'image'=>array('gif','jpg','jpeg','png','bmp'),
		'file'=>array('zip','rar','gz','tar','7z'),
		'music'=>array('mp3','wma')
		);
	//
	protected $_max_size = 10485760;  //10M
	// 不允许上传的文件类型
	protected $_no_allow_type = array('php','py','pl','asp','exe');
	// 允许上传文件类型
	protected $_allow_type = array();
	// 文件保存路径
	public $_save_path = '';
	// 文件扩展名
	public $_file_name = '';
	public $_file_ext = '';
	public $_file_save_path = '';
	// 错误
	public $_error = '';

	/**
	 * 构造函数
	 *
	 */
	public function __construct(){
		parent::__construct();
	}

	/**
	 * 上传操作
	 *
	 * @param string $save_path 保存目录
	 * @param string $field_name 上传input名
	 * @param int $max_size 文件大小限制 0为不限制
	 * @param string $filename 保存的文件名，默认自动生成
	 * @param mixed $type 上传文件类型，可以使image等标志，doc,xsl等单个文件类型，array('zip','rar')类型的数组
	 */
	public function doUpload($save_path,$field_name,$max_size=0,$filename='',$type='image'){
		// 处理存储路径
		if ( !$this->checkSavePath($save_path) ){
			return false;
		}
		if ( substr($save_path,-1)!='/' ){
			$save_path .= '/';
		}
		$this->_save_path = $save_path;
		// 判断是否是可上传文件
		if ( !$this->isUpload($field_name) ){
			return false;
		}
		$this->_allow_type = $this->makeAllowType($type);
		if ( empty($this->_allow_type) ){
			$this->_error = '未设置允许上传的文件类型';
			return false;
		}
		if ( !in_array($this->_file_ext,$this->_allow_type) ){
			$this->_error = '此文件类型不允许上传，允许上传的文件类型：'.implode('、',$this->_allow_type);
			return false;
		}
		// 将文件名中的非法字符去掉
		$filename = str_replace(array('\\','/',':','*','?','"','<','>','|'),array('','','','','','','','',''),$filename);
		if ( empty($filename)||!is_string($filename) ){
			$filename = date("Ymd_His_".rand(100000,999999));
		}
		$this->_file_name = $filename;
		if ( $max_size<0 ){
			$max_size = 0;
		}
		$this->_max_size = $max_size;
		if ( $this->_max_size&&$_FILES[$field_name]['size']>$this->_max_size ){
			$this->_error = '文件大小不能超过 '.ceil($this->_max_size/1024).'K('.$this->_max_size.' Bytes)';
			return false;
		}
		$this->_file_save_path = $this->_save_path.$this->_file_name.'.'.$this->_file_ext;
		// 开始上传
		if ( move_uploaded_file($_FILES[$field_name]['tmp_name'],$this->_file_save_path) ){
			return true;
		}
		else {
			$this->_error = '文件上传失败';
			return false;
		}
	}

	/**
	 * 创建目录
	 *
	 * @param 目录地址 $dir
	 * @param 创建权限 $mode
	 * @return bool
	 */
	function mk_dir($dir, $mode = 0755){
		if ( is_dir($dir)||@mkdir($dir,$mode) ){
			return true;
		}
		if ( !mk_dir(dirname($dir),$mode) ){
			return false;
		}
		return @mkdir($dir,$mode);
	}

	/**
	 * 检查保存目录是否设置正确
	 *
	 * @param string		$save_path
	 * @return bool
	 */
	public function checkSavePath($save_path){
		if ( empty($save_path) ){
			$this->_error = '未提供保存路径';
			return false;
		}
		if ( !$this->mk_dir($save_path) ){
			$this->_error = '尝试创建目录失败';
			return false;
		}
		if ( !is_dir($save_path) ){
			$this->_error = '文件保存路径应该是一个目录';
			return false;
		}
		if ( !is_writable($save_path) ){
			$this->_error = '文件保存路径应该可写';
			return false;
		}
		return true;
	}

	/**
	 * 根据$type类型，生成允许上传扩展名的数组
	 *
	 * @param mixed $type		可以使image等标志，doc,xsl等单个文件类型，array('zip','rar')类型的数组
	 */
	public function makeAllowType($type='image'){
		//判断格式
		$allow_type = array();
		if ( empty($type) ){
			return $allow_type;
		}
		if ( is_string($type) ){
			$type = trim(strtolower($type));
			if ( array_key_exists($type,$this->_type) ){
				$allow_type = $this->_type[$type];
			}
			else {
				$allow_type[] = $type;
			}
		}
		elseif ( is_array($type) ){
			foreach ($type as $v){
				if ( is_string($v) ){
					$allow_type[] = strtolower(trim($v));
				}
			}
		}
		return $allow_type;
	}

	/**
	 * 判断是否可上传
	 *
	 * @param string	$field_name		上传的field名字
	 * @return bool
	 */
	public function isUpload($field_name){
		if ( isset($_FILES[$field_name]) ){
			if ( !is_uploaded_file($_FILES[$field_name]['tmp_name']) ){
				$this->_error = '非法上传';
				return false;
			}
			if ( $_FILES[$field_name]['size']<1 ){
				$this->_error = '上传的文件为空';
				return false;
			}
			// 获取文件后缀名
			$file_name = stripslashes($_FILES[$field_name]['name']);
			$ext = strrpos( $file_name,'.');
			if ( $ext===false||$ext==0 ){
				$this->_error = '无法获取扩展名';
				return false;
			}
			$this->_file_ext = strtolower( substr($file_name,$ext+1) );
			if ( !$this->_file_ext ){
				$this->_error = '扩展名为空';
				return false;
			}
			if ( in_array($this->_file_ext,$this->_no_allow_type) ){
				$this->_error = '此文件类型禁止上传';
				return false;
			}
			return true;
		}
		else {
			$this->_error = '未选择要上传的文件';
			return false;
		}
	}

	/**
	 *获取上传列表
	 */
	public function getUploadList($page,$num,$findkey='',$order='id',$fields='*') {
		$numrows = intval($num);
		$page = (intval($page) > 0) ? intval($page) : 1;
		$offset = ($page -1) * $numrows;
		#
		$where = is_array($findkey) ? implode(' AND ', $findkey) : $findkey;
		$where = empty ($where) ? '' : ' WHERE ' . $where;
		#
		$orderby = ($orderby == '+') ? 'ASC' : 'DESC';
		$order = empty ($order) ? '' : (' ORDER BY ' . $order . ' ' . $orderby);
		#
		$limits =  '  LIMIT '.$offset.','.$numrows;
		#
		$sql = 'SELECT '. $fields . ' FROM ' . '#happy_upload';
		$sql .= $where . $order . $limits;
		#
		return $this->_db->getAll($sql);
	}


	/**
	 *统计上传数量
	 */
	public function getUploadCount($findkey='') {
		$where = is_array($findkey) ? implode(' AND ', $findkey) : $findkey;
		$where = empty ($where) ? '' : ' WHERE ' . $where;
		$sql = 'SELECT count(*) FROM #happy_upload';
		$sql .= $where;
		return $this->_db->getOne($sql);
	}
}
//类定义结束
?>